
package com.zdkj.subway.check.service.impl.subwayRat.transferdiff;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zdkj.common.core.exceltools.MultipartFileToFile;
import com.zdkj.subway.check.dvo.SwCkClearingTransferDiffReasonDvo;
import com.zdkj.subway.check.dvo.SwCkClearingTransferDiffReasonResultDvo;
import com.zdkj.subway.check.entity.Page;
import com.zdkj.subway.check.entity.SwCkClearingTransferDiffReason;
import com.zdkj.subway.check.enums.ResultDetailMsg;
import com.zdkj.subway.check.mapper.SwCkClearingTransferDiffReasonMapper;
import com.zdkj.subway.check.result.Result;
import com.zdkj.subway.check.util.DateFormat;
import com.zdkj.subway.check.util.LocalDateConverter;
import com.zdkj.subway.check.util.LocalDateTimeConverter;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * （清分ACC）清分及划账数据差异原因表
 *
 * @author lijie
 * @date 2020-12-20
 */
@Service
@Transactional
@Slf4j
@AllArgsConstructor
public class SwCkClearingTransferDiffReasonServiceImpl extends ServiceImpl<SwCkClearingTransferDiffReasonMapper, SwCkClearingTransferDiffReason> {
    private static final Logger LOGGER = LoggerFactory.getLogger(SwCkClearingTransferDiffReasonServiceImpl.class);
    SwCkClearingTransferDiffReasonMapper swCkClearingTransferDiffReasonMapper;

    /**
     * 查询系统报表清分数据差异原因列表
     *
     *
     * @param ids
     * @param searchDate
     * @param diffSource
     * @param sendStatus
     * @return
     */
    public List<SwCkClearingTransferDiffReasonResultDvo> getTransferDiffList(Page page, String ids, String searchDate, String diffSource, Integer sendStatus) {
        List<SwCkClearingTransferDiffReasonDvo> swCkClearingTransferDiffReasonDvos = swCkClearingTransferDiffReasonMapper.getTransferDiffList(page, ids, searchDate, diffSource, sendStatus);
        List<SwCkClearingTransferDiffReasonResultDvo> resultDvoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(swCkClearingTransferDiffReasonDvos)) {
            swCkClearingTransferDiffReasonDvos.stream().forEach(sqlBean -> {
                SwCkClearingTransferDiffReasonResultDvo resultDvo = new SwCkClearingTransferDiffReasonResultDvo();
                BeanUtil.copyProperties(sqlBean, resultDvo);
                switch (sqlBean.getDiffSource()) {
                    case 1:
                        resultDvo.setAlrealIncomeMoney(sqlBean.getRerealIncomeMoney());
                        break;
                    case 2:
                        resultDvo.setAlrealIncomeMoney(sqlBean.getQrrealIncomeMoney());
                        resultDvo.setAldiffAccMoney(sqlBean.getQrdiffAccMoney());
                        resultDvo.setAlaccMoney(sqlBean.getQraccMoney());
                        break;
                    case 3:
                        resultDvo.setAlrealIncomeMoney(sqlBean.getAcrealIncomeMoney());
                        resultDvo.setAldiffAccMoney(sqlBean.getAcdiffAccMoney());
                        resultDvo.setAlaccMoney(sqlBean.getAcaccMoney());
                        break;
                }
                resultDvoList.add(resultDvo);
            });
        }
        return resultDvoList;
    }

    /**
     * 批量完善差异原因
     *
     * @param jsonObject
     * @return
     */
    public Result saveMutilCleardDiff(JSONObject jsonObject) {
        //{"thisday":"2020-12-20","diffdesc":"qwe","ids":[3]}
        JSONArray ids = JSONArray.parseArray(jsonObject.getString("ids"));
        if (CollectionUtil.isNotEmpty(ids)) {
            List<SwCkClearingTransferDiffReason> searchList = (List) this.listByIds(JSONArray.parseArray(JSONObject.toJSONString(ids), Long.class));
            List<SwCkClearingTransferDiffReason> updateList = new ArrayList<>();
            //批量修改差异表状态
            searchList.forEach(inbean -> {
                SwCkClearingTransferDiffReason tempBean = new SwCkClearingTransferDiffReason();
                tempBean.setId(inbean.getId());
                tempBean.setIsReplay(1);
                tempBean.setDiffReason(jsonObject.getString("diffdesc"));
                tempBean.setDiffReasonTime(LocalDateTime.now());
                Duration duration = Duration.between(inbean.getCreateTime(), LocalDateTime.now());
                long days = duration.toDays(); //相差的天数
                //判断过期没
                int isExceed = 0;
                if (inbean.getReplayLimit() >= days) {
                    isExceed = 1;
                }
                if ("1".equals(inbean.getDiffSource())) {
                    swCkClearingTransferDiffReasonMapper.updateROT(inbean.getRelationId(), isExceed);
                } else if ("2".equals(inbean.getDiffSource())) {
                    swCkClearingTransferDiffReasonMapper.updateQR(inbean.getRelationId(), isExceed);
                } else if ("3".equals(inbean.getDiffSource())) {
                    swCkClearingTransferDiffReasonMapper.updateARF(inbean.getRelationId(), isExceed);
                }
                updateList.add(tempBean);
            });
            if (!this.updateBatchById(updateList)) {
                new Result(ResultDetailMsg.CHECK_UPDATE_ERROR);
            }
        }
        return new Result(ResultDetailMsg.OK);
    }

    /**
     * 批量下发差异
     *
     * @param jsonObject
     * @return
     */
    public Result sendMutilCleardDiff(JSONObject jsonObject) {
        JSONArray ids = JSONArray.parseArray(jsonObject.getString("ids"));
        if (CollectionUtil.isNotEmpty(ids)) {
            List<SwCkClearingTransferDiffReason> searchList = (List) this.listByIds(JSONArray.parseArray(JSONObject.toJSONString(ids), Long.class));
            List<SwCkClearingTransferDiffReason> updateList = new ArrayList<>();
            searchList.forEach(inbean -> {
                SwCkClearingTransferDiffReason tempBean = new SwCkClearingTransferDiffReason();
                tempBean.setId(inbean.getId());
                tempBean.setSendTime(LocalDateTime.now());
                tempBean.setSendStatus(1);
                updateList.add(tempBean);
                if (!this.updateBatchById(updateList)) {
                    new Result(ResultDetailMsg.CHECK_UPDATE_ERROR);
                }
            });
        }
        return new Result(ResultDetailMsg.OK);
    }

    /**
     * 差异原因导入
     *
     * @param file
     * @return
     */
    public Result saveBatchWithExcel(final MultipartFile file) throws Exception {
        File excelFile = MultipartFileToFile.multipartFileToFile(file);
        List<Map<Integer, String>> listMap = EasyExcel.read(excelFile).sheet().headRowNumber(3).doReadSync();
        List<SwCkClearingTransferDiffReason> listDb = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(listMap)) {
            MultipartFileToFile.delteTempFile(excelFile);
            for (int m = 0; m < listMap.size(); m++) {
                Map<Integer, String> data = listMap.get(m);
                // 返回每条数据的键值对 表示所在的列 和所在列的值
                log.info("读取到数据:{}", JSON.toJSONString(data));

                SwCkClearingTransferDiffReason tmpObj = new SwCkClearingTransferDiffReason();
                tmpObj.setId(new Double(Double.parseDouble(data.get(0))).longValue());//id
                if(StringUtils.isNotEmpty(data.get(2)) || StringUtils.isNotEmpty(data.get(3))){
                    //差异原因
                    tmpObj.setDiffReason(data.get(2));
                    if(StringUtils.isNotEmpty(data.get(3))){
                        //excel导入的日期格式2021-09-09
                        boolean date = DateFormat.isDate(data.get(3), "yyyy-MM-dd");
                        if(date){
                            //差异回复时间
                            tmpObj.setDiffReasonTime(DateFormat.DateTurnLocalDateTime(DateFormat.stringToDate(data.get(3))));
                        }else {
                            return new Result(ResultDetailMsg.MONDIFY_FILE_FAILD,listDb);
                        }
                    }
                }

                listDb.add(tmpObj);
            }
        }
        this.updateBatchById(listDb);
        return new Result(ResultDetailMsg.OK,listDb);
    }

    /**
     * 保存导入
     * @param jsonObject
     * @return
     */
    public Result saveBatch(JSONArray jsonObject) {
        List<JSONObject> reqList = JSONArray.parseArray(jsonObject.toJSONString(),JSONObject.class);
        if (CollectionUtil.isNotEmpty(reqList)){
            List<SwCkClearingTransferDiffReason> listDb = new ArrayList<>();
            reqList.forEach(tempJson -> {
                SwCkClearingTransferDiffReason tmpObj = new SwCkClearingTransferDiffReason();
                tmpObj.setId(Long.valueOf(tempJson.getLong("id")));//id
                //差异原因
                tmpObj.setDiffReason(tempJson.getString("diffReason"));
                //差异回复日期
                tmpObj.setDiffReasonTime(DateFormat.StringTurnLocalDateTime(tempJson.getString("diffReasonTime")));
                listDb.add(tmpObj);
            });
            if (!this.updateBatchById(listDb)) {
                new Result(ResultDetailMsg.CHECK_UPDATE_ERROR);
            }
        }
        return new Result(ResultDetailMsg.OK);
    }

    /**
     * 导出
     * @param ids
     * @param searchDate
     * @param diffSource
     * @param sendStatus
     * @param response
     */
    public void export(String ids, String searchDate, String diffSource, Integer sendStatus, HttpServletResponse response) {
        List<SwCkClearingTransferDiffReasonResultDvo> transferDiffList = this.getTransferDiffList(null,ids, searchDate, diffSource, sendStatus);
        if(CollectionUtil.isNotEmpty(transferDiffList)){
            BigDecimal decimal100 = new BigDecimal("100");
            for (SwCkClearingTransferDiffReasonResultDvo resultDvo : transferDiffList) {
                if(resultDvo.getDiffReasonTime() != null){
                    resultDvo.setDiffReasonDate(resultDvo.getDiffReasonTime().toLocalDate());
                }
                resultDvo.setAlrealIncomeMoney(ifNullDecimal(resultDvo.getAlrealIncomeMoney()).divide(decimal100));
                resultDvo.setReaccReceivableMoney(ifNullDecimal(resultDvo.getReaccReceivableMoney()).divide(decimal100));
                resultDvo.setReaccPayableMoney(ifNullDecimal(resultDvo.getReaccPayableMoney()).divide(decimal100));
                resultDvo.setRediffAccRealMoney(ifNullDecimal(resultDvo.getRediffAccRealMoney()).divide(decimal100));
                resultDvo.setRediffAccReceivableMoney(ifNullDecimal(resultDvo.getRediffAccReceivableMoney()).divide(decimal100));
                resultDvo.setAlaccMoney(ifNullDecimal(resultDvo.getAlaccMoney()).divide(decimal100));
                resultDvo.setAldiffAccMoney(ifNullDecimal(resultDvo.getAldiffAccMoney()).divide(decimal100));
            }
            String sheetName = "单程票应收-实收统计";
            String excelName = "/static/excel/export/SwCkClarifyManagementOnewayExcelTemplate.xlsx";
            if("2".equals(diffSource)){
                sheetName = "二维码应收-应付差异统计";
                excelName = "/static/excel/export/SwCkClarifyManagementQrExcelTemplate.xlsx";
            }
            if("3".equals(diffSource)){
                sheetName = "人脸电子票应收应付差异统计";
                excelName = "/static/excel/export/SwCkClarifyManagementFaceExcelTemplate.xlsx";
            }
            InputStream excelTemplateIs = null;
            try {
                response.reset(); // 非常重要
                response.setContentType("application/vnd.ms-excel");
                response.setCharacterEncoding("utf-8");
                final String fileName = URLEncoder.encode(sheetName, "UTF-8");
                response.setHeader("Content-disposition", "attachment;filename=" + fileName + System.currentTimeMillis() + ".xlsx");

                // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
                // {} 代表普通变量 {.} 代表是list的变量
                excelTemplateIs = this.getClass().getResourceAsStream(excelName);

                ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).registerConverter(new LocalDateTimeConverter()).registerConverter(new LocalDateConverter()).withTemplate(excelTemplateIs).build();
                WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).build();
                // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行，然后下面的数据往后移动。默认 是false，会直接使用下一行，如果没有则创建。
                // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了，所以慎用
                // 简单的说 如果你的模板有list,且list不是最后一行，下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
                // 如果数据量大 list不是最后一行 参照另一个
                FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.FALSE).build();
                excelWriter.fill(transferDiffList, fillConfig, writeSheet);
                excelWriter.finish();

            } catch (Exception e) {
                e.printStackTrace();
                LOGGER.error("导出"+sheetName+"异常");
            } finally {
                if(excelTemplateIs != null){
                    try {
                        excelTemplateIs.close();
                    } catch (IOException ioe) {
                        ioe.printStackTrace();
                    }
                }
            }
        }
    }

    /**
     * 校验null
     * @param amount
     * @return
     */
    private BigDecimal ifNullDecimal(BigDecimal amount) {
        if(amount == null){
            return new BigDecimal("0");
        }
        return amount;
    }
}
